/**
 * 
 */
package com.jd.event.spring.config;

import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.DefaultDocumentLoader;
import org.springframework.beans.factory.xml.DocumentLoader;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.xml.XmlValidationModeDetector;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import com.jd.event.EventContainer;

/**
 * @author luolishu
 * 
 */
public class EventScanBeanDefinitionParser implements BeanDefinitionParser {
	final ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();
	final DocumentLoader documentLoader = new DefaultDocumentLoader();
	static final String SCHEDULER_NAME = "scheduler";
	final EventContainer container = new EventContainer();

	@Override
	public BeanDefinition parse(Element element, ParserContext context) {
		try {
			String locationPattern = element.getAttribute("location");
			Resource[] resources = resourcePatternResolver
					.getResources(locationPattern);

			for (Resource res : resources) {
				this.parseResource(res, context);
			}

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	private void parseResource(Resource res, ParserContext context)
			throws Exception {
		InputSource inputSource = new InputSource(res.getInputStream());
		Document document = documentLoader.loadDocument(inputSource, null,
				null, XmlValidationModeDetector.VALIDATION_NONE, false);

		NodeList nodeList = document.getDocumentElement().getChildNodes();
		int len = nodeList.getLength();

		for (int i = 0; i < len; i++) {
			Node node = nodeList.item(i);
			if (!SCHEDULER_NAME.equals(node.getNodeName())) {
				continue;
			}
			RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(
					SpringGroupScheduledService.class);
			Element element = (Element) node;
			String id = element.getAttribute("id");
			String group = element.getAttribute("group");
			String theadpoolSize = element.getAttribute("theadpool-size");
			Properties p = new Properties();
			p.setProperty(EventContainer.THREAD_POOL_SIZE, theadpoolSize);
			container.createGroup(group, p);

			rootBeanDefinition.getPropertyValues().addPropertyValue("group",
					group);
			rootBeanDefinition.getPropertyValues().addPropertyValue(
					"container", container);
			setListeners(element, rootBeanDefinition);
			context.getRegistry()
					.registerBeanDefinition(id, rootBeanDefinition);

		}

	}

	private void setListeners(Element element,
			RootBeanDefinition rootBeanDefinition) {
		NodeList nodeList = element.getChildNodes();
		int len = nodeList.getLength();
		if (len <= 0) {
			return;
		}
		List<ListenerDescription> listnerDescs = new ArrayList<ListenerDescription>(
				len);
		for (int i = 0; i < len; i++) {
			Node node = nodeList.item(i);
			if (!"listener".equals(node.getNodeName())) {
				continue;
			}
			Element listenerEl = (Element) node;
			String ref = listenerEl.getAttribute("ref");
			String className = listenerEl.getAttribute("class");
			ListenerDescription desc = new ListenerDescription();
			desc.setClassName(className);
			desc.setRef(ref);
			listnerDescs.add(desc);
		}
		rootBeanDefinition.getPropertyValues().addPropertyValue("listnerDescs",
				listnerDescs);
	}

}
